/**
 * 类名：LoginAction
 * 创建日期： 2014-10-12 下午8:03:35
 * 
 */
package com.erms.action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;

import org.apache.struts2.ServletActionContext;

import net.sf.json.JSONObject;

import com.erms.Config;
import com.erms.bean.Course;
import com.erms.bean.Department;
import com.erms.bean.Major;
import com.erms.bean.StudentTeach;
import com.erms.bean.Teach;
import com.erms.bean.User;
import com.erms.dao.CourseDAO;
import com.erms.dao.DepartmentDAO;
import com.erms.dao.MajorDAO;
import com.erms.dao.StudentTeachDAO;
import com.erms.dao.TeachDAO;
import com.erms.dao.UserDAO;
import com.erms.domain.XKCollecter;
import com.erms.util.StringUtil;
import com.erms.util.TimeUtil;

/**
 * 备注：
 * 
 * @author hmb
 * 
 */
public class LoginAction extends BaseAction {

	private static final long	serialVersionUID	= -8164396291254138998L;

	private String				forwardUrl			= null;

	private boolean				remember;
	// 用于自动填写登录页面的账户名密码
	private String				name;
	private String				password;

	private User				user;
	private UserDAO				userDAO;
	private DepartmentDAO		departmentDAO;
	private MajorDAO			majorDAO;
	private StudentTeachDAO		studentTeachDAO;
	private TeachDAO			teachDAO;
	private CourseDAO			courseDAO;

	public String getForwardUrl() {

		return forwardUrl;
	}

	public void setForwardUrl(String forwardUrl) {

		this.forwardUrl = forwardUrl;
	}

	public boolean isRemember() {

		return remember;
	}

	public void setRemember(boolean remember) {

		this.remember = remember;
	}

	public final String getName() {

		return this.getValueFromCookie(KEY_USERNAME);
	}

	public void setName(String name) {

		this.name = name;
	}

	public final String getPassword() {

		return StringUtil.fromBase64(this.getValueFromCookie(KEY_PASSWORD));
	}

	public void setPassword(String password) {

		this.password = password;
	}

	public CourseDAO getCourseDAO() {

		return courseDAO;
	}

	public void setCourseDAO(CourseDAO courseDAO) {

		this.courseDAO = courseDAO;
	}

	public TeachDAO getTeachDAO() {

		return teachDAO;
	}

	public void setTeachDAO(TeachDAO teachDAO) {

		this.teachDAO = teachDAO;
	}

	public User getUser() {

		return user;
	}

	public void setUser(User user) {

		this.user = user;
	}

	public UserDAO getUserDAO() {

		return userDAO;
	}

	public void setUserDAO(UserDAO userDAO) {

		this.userDAO = userDAO;
	}

	public DepartmentDAO getDepartmentDAO() {

		return departmentDAO;
	}

	public void setDepartmentDAO(DepartmentDAO departmentDAO) {

		this.departmentDAO = departmentDAO;
	}

	public MajorDAO getMajorDAO() {

		return majorDAO;
	}

	public void setMajorDAO(MajorDAO majorDAO) {

		this.majorDAO = majorDAO;
	}

	public StudentTeachDAO getStudentTeachDAO() {

		return studentTeachDAO;
	}

	public void setStudentTeachDAO(StudentTeachDAO studentTeachDAO) {

		this.studentTeachDAO = studentTeachDAO;
	}

	private void validateID() {

		logger.debug("验证用户名");
		if (user == null) {
			logger.debug("没有用户数据，将会跳转到登录页");
			addFieldError(Config.USER_NAME, "没有用户数据");
			return;
		}
		if (StringUtil.isNull(user.getId())) {
			logger.debug("用户名为空");
			addFieldError(Config.USER_NAME, "用户名不能为空");
		} else if (user.getId().trim().length() > 15) {
			logger.debug("学号或工号太长");
			addFieldError(Config.USER_NAME, "学号或工号不能大于15位");
		}
	}

	private void validatePassword() {

		logger.debug("验证密码");
		if (user == null) return;
		if (StringUtil.isNull(user.getPassword())) {
			logger.debug("密码为空");
			addFieldError("password", "密码不能为空");
		} else if (!user.getPassword().matches("^\\w+$")) {
			logger.debug("密码不正确");
			addFieldError("password", "密码只能为数字、26个英文字母或者下划线组成的字符串");
		} else if (user.getPassword().trim().length() > 20) {
			logger.debug("密码太长");
			addFieldError("password", "密码不能大于20位");
		}
	}

	public void validateLogin() {

		// TODO 自动生成的方法存根
		validateID();
		validatePassword();
	}

	// 仅用于异步验证用户名是否合法，注意这里不涉及密码验证，最好不要应用数据库取出的数据
	public String ajaxLogin() {

		logger.debug("ajax验证用户名");
		JSONObject object = new JSONObject();
		object.put("timestamp", TimeUtil.getTimeStamp());
		if (user != null && StringUtil.isNull(user.getId())) {
			if (userDAO.findById(user.getId()) != null) {
				object.put("result", "成功");
			} else {
				object.put("result", "失败");
				object.put("reson", "用户名不存在或首次登陆");
			}
		} else {
			object.put("result", "失败");
			object.put("reson", "用户名不合法");
		}
		setJsonText(object.toString());
		logger.debug(object.toString());
		return SUCCESS;
	}

	public String login() {

		logger.debug("请求登录用户 " + user.getId());
		logger.debug("forwardUrl = " + forwardUrl);
		setCurrentUri(forwardUrl);
		User realUser = userDAO.findById(user.getId());
		if (realUser == null) { return visitXuanKeServerIfNeeded(); }
		if (user.getPassword().equals(realUser.getPassword())) {
			user = realUser;
			return onLoginSuccess();
		} else {
			return LOGIN;
		}
	}

	public String logout() {

		// 没做更多处理

		logger.debug(getSession().getAttribute(Config.USER_NAME) + " 用户注销了");
		getSession().removeAttribute(Config.USER_NAME);
		getSession().removeAttribute("type");
		return SUCCESS;
	}

	/**
	 * @see com.erms.action.BaseAction#execute()
	 * @return
	 * @throws Exception
	 */
	@Override
	public String execute() throws Exception {

		// TODO 自动生成的方法存根
		logger.debug("即将进入登录页");
		return SUCCESS;
	}

	// 需要说明一点，目前没有访问抓取教师信息的能力，所以以下操作是针对学生而言的。
	//目前特定教师信息应该从开课信息表读取并保存至用户表，
	@SuppressWarnings("rawtypes")
	private String visitXuanKeServerIfNeeded() {

		XKCollecter collecter = new XKCollecter(user.getId(),
				user.getPassword());
		if (!collecter.login()) {
			logger.debug("教务处不存在该用户信息");
			return INPUT;
		}

		// 鉴于学院数据较小，这里一次性全部取出，并转化为哈希表
		List departmentList = departmentDAO.findAll();
		Map<String, Integer> depMap = new HashMap<>();
		for (int i = 0; i < departmentList.size(); i++) {
			Department department = (Department) departmentList.get(i);
			depMap.put(department.getName(), department.getId());
		}

		// 获取用户信息
		user = collecter.getUserInfo();
		if (user == null) { return INPUT; }
		try {
			String depName = user.getDepartment().getName();
			String majorName = user.getMajor().getName();
			// //预处理，根据已知情况修改学院专业名称以符合数据库已有信息
			if ("计算机科学与技术学院".equals(depName)) {
				depName = "计算机学院";// 坑爹
			}
			majorName = majorName.replace("专业", "");

			// ////////////
			logger.debug("学生信息:" + user.getId() + " " + user.getName() + " "
					+ depName + " " + majorName + " " + user.getClassNum());

			user.setType(STUDENT);
			Major userMajor = (Major) majorDAO.findByName(majorName).get(0);
			user.getDepartment().setId(depMap.get(depName));
			user.setMajor(userMajor);
			// 这里只有学院专业的名字，而没有id，user表中存的是对应外键id
			userDAO.save(user);
			// 获取选课表，即课程表，并且在第一条记录中包含了用户信息
			List<StudentTeach> schedule = collecter.getSchedule();
			int n = schedule.size();

			for (int i = 0; i < n; i++) {
				StudentTeach studentTeach = schedule.get(i);
				studentTeachDAO.merge(studentTeach);

			}

		} catch (Exception e) {
			logger.debug("注意：出现了数据库中不存在的学院或专业信息", e);
			return INPUT;
		}

		return onLoginSuccess();

	}

	private String onLoginSuccess() {

		logger.debug("用户 " + user.getName() + " 刚刚登陆了");
		logger.debug("用户部分信息为：" + user.getId() + " " + user.getClassNum());
		logger.debug("remember? " + remember);
		if (remember) {
			int expiry = 60 * 60 * 24 * 30;
			this.addCookie(KEY_USERNAME, user.getId(), expiry);
			this.addCookie(KEY_PASSWORD,
					StringUtil.toBase64(user.getPassword()), expiry);
		} else {
			this.removeCookie(KEY_USERNAME);
			this.removeCookie(KEY_PASSWORD);
		}
		getSession().setAttribute(KEY_USERNAME, user.getId());
		String identity = user.getType();
		getSession().setAttribute(KEY_TYPE, identity);
		logger.debug("用户身份：" + identity);
		if (!StringUtil.isNull(getForwardUrl())) { return "forward"; }
		return SUCCESS;
	}

}
